package com.bonnemai.eqd.client;

import java.util.Date;
import java.util.logging.Logger;

import org.zenika.widget.client.datePicker.DatePicker;

import com.bonnemai.eqd.shared.Results;
import com.bonnemai.eqd.shared.Vanilla;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.HasChangeHandlers;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.DoubleBox;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class StupidPricer implements EntryPoint {
	private static Logger LOG=Logger.getLogger(StupidPricer.class.getName());
	/**
	 * The message displayed to the user when the server cannot be reached or
	 * returns an error.
	 */
	private ListBox typePanel=new ListBox();
	private DoubleBox strikePanel = new DoubleBox();
	private DoubleBox spotPanel = new DoubleBox();
	private DoubleBox  riskFreeRatePanel = new DoubleBox ();

	private DoubleBox volatilityPanel = new DoubleBox();
	private DoubleBox dividendYieldPanel = new DoubleBox();

	private DatePicker todayDatePanel = new DatePicker ();
	private DatePicker settlementDatePanel = new DatePicker ();
	private DatePicker maturityDatePanel = new DatePicker ();
	
	// Outputs
	private DoubleBox npvPanel = new DoubleBox ();
	private DoubleBox deltaPanel = new DoubleBox();
	private DoubleBox gammaPanel = new DoubleBox();

	private Label errorLabel = new Label();
	private boolean initFinished=false;
	
	// Inputs
	Widget[] inputList = {
			typePanel,
			strikePanel ,
			spotPanel ,
			riskFreeRatePanel ,
			volatilityPanel ,
			dividendYieldPanel ,
			todayDatePanel ,
			settlementDatePanel ,
			maturityDatePanel };

	String[] inputListName = {
			"Type",
			"Strike",
			"Spot",
			"Risk Free Rate",
			"Volatility",
			"Dividend Yield",
			"Today Date",
			"Settlement Date",
			"Maturity Date",
			"Date Picker"};


	// Outputs
	Widget[] outputList = {
			npvPanel,
			deltaPanel,
			gammaPanel,
			errorLabel
	};

	String[] outputListName = {
			"NPV",
			"Delta",
			"Gamma",
			"" // for the errors
	};
	
	/**
	 * Create a remote service proxy to talk to the server-side Greeting service.
	 */
	private final PricingServiceAsync pricingService = GWT.create(PricingService.class);

	/**
	 * This is the entry point method.
	 */
	public void onModuleLoad() {
		FlexTable inputTable = new FlexTable();
		
		for (int iField=0;iField<inputList.length;iField++){
			inputTable.setText( iField, 0, inputListName[iField]);
			inputTable.setWidget( iField, 1, inputList[iField]);					

			((HasChangeHandlers) inputList[iField]).addChangeHandler(new PriceChangeHandler());
		}

		for (int iField=0;iField<outputList.length;iField++){
			inputTable.setText( inputList.length+iField, 0, outputListName[iField]);
			inputTable.setWidget( inputList.length+iField, 1, outputList[iField]);					
		}
		
		initValues();
		
		RootPanel.get("stupidPricer").add(inputTable);
	}
	

	private void initValues(){

		typePanel.addItem("Call");
		typePanel.addItem("Put");					
		typePanel.setValue(0, "Call");

		strikePanel.setValue(new Double(100));
		spotPanel.setValue(new Double(100));

		dividendYieldPanel.setValue(new Double(0.03));
		riskFreeRatePanel.setValue(new Double(0.05));
		volatilityPanel.setValue(new Double(0.25));

		Date today = new Date();
		Date matu= new Date(today.getTime() + 365 * 24*60*60*1000L);// one Year
		
		todayDatePanel.setSelectedDate(today);
		settlementDatePanel.setSelectedDate(today);
		maturityDatePanel.setSelectedDate(matu);

		//		Add more greeks ?
		npvPanel.setEnabled(false);
		deltaPanel.setEnabled(false);
		gammaPanel.setEnabled(false);
		
		initFinished=true;
	}

	private void price() {
		LOG.info("Pricing");
		
		errorLabel.setText("");
		npvPanel.setValue(null);
		deltaPanel.setValue(null);
		gammaPanel.setValue(null);

		if(initFinished){
			Vanilla vanilla=new Vanilla();
			if (typePanel.getSelectedIndex()==0){
				vanilla.setType("Call");	
			}else{
				vanilla.setType("Put");
			}
			vanilla.setStrike(strikePanel.getValue()); 
			vanilla.setSpot(spotPanel.getValue());
			vanilla.setRiskFreeRate(riskFreeRatePanel.getValue() );
			vanilla.setVolatility(volatilityPanel.getValue());
			vanilla.setDividendYield(dividendYieldPanel.getValue());
			vanilla.setTodaysDate(todayDatePanel.getSelectedDate());
			vanilla.setSettlementDate(settlementDatePanel.getSelectedDate());
			vanilla.setMaturityDate(maturityDatePanel.getSelectedDate());
	
			pricingService.priceServer(vanilla, new AsyncCallback<Results>() {
				public void onFailure(Throwable caught) {							
					LOG.warning("Warning: "+caught.getMessage());
					// errorLabel.setText(caught.getMessage());
				}
	
				public void onSuccess(Results results) {
					if(	results.getError()!=null){
						errorLabel.setText(results.getError());
					}else{
						npvPanel.setValue(results.getNpv());
						deltaPanel.setValue(results.getDelta());
						gammaPanel.setValue(results.getGamma());
					}
				}
			});
		}
	}
	
	public Double getNpv() {
		return npvPanel.getValue();
	}

	private class PriceChangeHandler implements ChangeHandler {
		@Override
		public void onChange(ChangeEvent event) {
			price();
		}
	}
}
